using ColorFillGame.Domain.Entities;
using ColorFillGame.Domain.Exceptions;
using ColorFillGame.Domain.Repositories;
using ColorFillGame.Domain.Services;
using ColorFillGame.Domain.ValueObjects;
using MediatR;
using Microsoft.Extensions.Logging;

namespace ColorFillGame.Application.Commands.Game;

public class PaintActionCommandHandler : IRequestHandler<PaintActionCommand>
{
    private readonly IGameRepository _gameRepository;
    private readonly IPlayerRepository _playerRepository;
    private readonly IGameService _gameService;
    private readonly ILogger<PaintActionCommandHandler> _logger;

    public PaintActionCommandHandler(
        IGameRepository gameRepository,
        IPlayerRepository playerRepository,
        IGameService gameService,
        ILogger<PaintActionCommandHandler> logger)
    {
        _gameRepository = gameRepository;
        _playerRepository = playerRepository;
        _gameService = gameService;
        _logger = logger;
    }

    public async Task Handle(PaintActionCommand request, CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogDebug("Processing PaintActionCommand: GameId={GameId}, PlayerId={PlayerId}, X={X}, Y={Y}", 
                request.GameId, request.PlayerId, request.X, request.Y);

            // 获取游戏
            var game = await _gameRepository.GetByIdAsync(request.GameId);
            if (game == null)
            {
                _logger.LogWarning("Game not found: {GameId}", request.GameId);
                throw new GameNotFoundException(request.GameId);
            }
            _logger.LogDebug("Found game: {GameId}, Status={Status}, GridSize={GridSize}", 
                game.Id, game.Status, game.GridSize);

            // 检查游戏是否正在进行（暂时放宽限制，允许Created状态下也能涂色用于调试）
            if (game.Status != GameStatus.InProgress && game.Status != GameStatus.Created)
            {
                _logger.LogWarning("Game not in progress or created: {GameId}, CurrentStatus={Status}", 
                    game.Id, game.Status);
                throw new DomainException($"Game is not in progress or created. Current status: {game.Status}");
            }
            
            if (game.Status == GameStatus.Created)
            {
                _logger.LogInformation("Allowing paint action in Created status for debugging: {GameId}", game.Id);
            }

            // 获取玩家
            var player = await _playerRepository.GetByIdAsync(request.PlayerId);
            if (player == null)
            {
                _logger.LogWarning("Player not found: {PlayerId}", request.PlayerId);
                throw new PlayerNotFoundException(request.PlayerId);
            }
            _logger.LogDebug("Found player: {PlayerId}, GameId={PlayerGameId}, HasColor={HasColor}", 
                player.Id, player.GameId, player.Color != null);

            // 检查玩家是否属于该游戏
            if (player.GameId != request.GameId)
            {
                _logger.LogWarning("Player does not belong to this game: PlayerId={PlayerId}, PlayerGameId={PlayerGameId}, TargetGameId={TargetGameId}", 
                    player.Id, player.GameId, request.GameId);
                throw new DomainException("Player does not belong to this game.");
            }

            // 检查玩家是否有颜色
            if (player.Color == null)
            {
                _logger.LogWarning("Player does not have a color assigned: {PlayerId}", player.Id);
                throw new DomainException("Player does not have a color assigned.");
            }

            // 创建位置对象
            _logger.LogDebug("Creating Position object with X={X}, Y={Y}", request.X, request.Y);
            var position = new Position(request.X, request.Y); // 修复命名空间错误
            _logger.LogDebug("Position object created successfully");

            // 验证位置是否有效
            if (!position.IsValid(game.GridSize))
            {
                _logger.LogWarning("Invalid position: X={X}, Y={Y}, GridSize={GridSize}", 
                    position.X, position.Y, game.GridSize);
                throw new ColorFillGame.Domain.Exceptions.InvalidPositionException(position.X, position.Y);
            }
            _logger.LogDebug("Position is valid: X={X}, Y={Y}, GridSize={GridSize}", 
                position.X, position.Y, game.GridSize);

            // 执行涂色操作
            _logger.LogDebug("Performing paint action");
            _gameService.PerformPaintAction(game, player, position);
            _logger.LogDebug("Paint action performed successfully");

            // 更新游戏状态
            _logger.LogDebug("Updating game state");
            await _gameRepository.UpdateAsync(game);
            await _gameRepository.SaveChangesAsync();
            _logger.LogDebug("Game state updated successfully");

            // 检查胜负条件
            if (_gameService.CheckWinCondition(game, player))
            {
                _logger.LogInformation("Player won the game: PlayerId={PlayerId}, GameId={GameId}", 
                    player.Id, game.Id);
                game.CompleteGame();
                await _gameRepository.UpdateAsync(game);
                await _gameRepository.SaveChangesAsync();
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing PaintActionCommand: {Message}", ex.Message);
            throw;
        }
    }
}